# -*- coding:utf-8 -*-
import json
import logging
import os
import subprocess
import threading
from datetime import datetime

from django.conf import settings
from django_redis import get_redis_connection

from Apps.UiTest.models import UiTestCase, UiTestCaseLog
from Apps.util.snowFlake import get_guid

redis_conn = get_redis_connection("default")
logger = logging.getLogger('django')


# 放入redis队列中
# redis_conn.rpush("UiTestListQueue", "893293823)
# 从缓存中获取，
# UiTestId = redis_conn.lpop("UiTestListQueue") if getattr(settings, "REDIS_ENABLE", False) else ""

def add_uitest_log(ui_case_id):
    case_instance = UiTestCase.objects.get(id=ui_case_id)
    obj = UiTestCaseLog.objects.create(case=case_instance, project=case_instance.project,
                                       case_url=case_instance.case_url)
    return obj.id


class RunUiTest:
    instance = None
    lock = threading.RLock()

    is_run_flag = False

    def __new__(cls, *args, **kwargs):
        if cls.instance:
            return cls.instance

        with cls.lock:
            cls.instance = object.__new__(cls)
            return cls.instance

    def _run_ui_test(self):
        """
        selenium-side-runner --server http://124.122.146.157:4444/wd/hub
        ./Downloads/test_bai.side --output-directory=results/projectName
        """
        run_ui_case_log_id = redis_conn.lpop("UiTestListQueue") if getattr(settings, "REDIS_ENABLE", False) else ""

        if run_ui_case_log_id:
            logger.info(f"#######正在运行caseLog:{run_ui_case_log_id.decode()}")
            logger.info(int(run_ui_case_log_id))

            # UI用例执行日志
            case_log_instance = UiTestCaseLog.objects.get(id=int(run_ui_case_log_id))
            case_log_instance.status = 2
            case_log_instance.save()

            # 将用例状态变更为执行中
            case_instance = UiTestCase.objects.get(id=case_log_instance.case.id)
            case_instance.run_status = 3
            case_instance.save()

            run_case_file_name = str(settings.BASE_DIR) + case_log_instance.case_url
            # logger.info(run_case_file_name)
            output_directory = os.path.join(settings.BASE_DIR, 'static', 'uioutput', f'{case_instance.id}',
                                            f"{case_log_instance.id}")
            command = f"selenium-side-runner --server {settings.DRIVER_HUB}  {run_case_file_name} --output-directory={output_directory}"
            start_time = datetime.now()
            p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, universal_newlines=True)
            # logger.info(p.stdout.read())
            p.wait()  # 因为subprocess 本身是多线程，所以要加等待，变成一个一个执行
            out, err = p.communicate()
            print(out)

            logger.info(out)
            if p.returncode == 0:
                logger.info("p-returncode为0")
            else:
                logger.info("p-returncode 不为 0")

            end_time = datetime.now()

            logger.info("########### UI测试用例执行结束caseLog:" + case_log_instance.id)
            logger.info("########### 记录执行结果")

            result_files = [os.path.join(output_directory, file) for file in os.listdir(output_directory)]
            with open(result_files[0], 'r') as f:
                result_json = json.loads(f.read())

            case_log_instance.status = 3
            case_log_instance.run_message = result_json
            case_log_instance.is_success = result_json["success"]
            case_log_instance.start_time = start_time
            case_log_instance.end_time = end_time
            case_log_instance.elapsed_time = end_time - start_time
            case_log_instance.save()

            case_instance.run_status = 4
            case_instance.save()

            # 递归执行下一个
            self._run_ui_test()

        if not run_ui_case_log_id:
            self.is_run_flag = False

    def run(self, data):
        # {'browser': 'chrome', 'id': '1761235035413164032'}
        browser = data["browser"]
        ui_case_id = data["id"]

        # 更新执行的浏览器
        try:
            case_instance = UiTestCase.objects.get(id=ui_case_id)
            case_instance.last_run_browser = browser
            case_instance.run_status = 2
            case_instance.save()
        except UiTestCase.DoesNotExist:
            raise KeyError(f"UI测试用例:{ui_case_id} 不存在")

        if self.is_run_flag:
            logger.info("有正在运行的，加入队列")
            case_log_id = add_uitest_log(ui_case_id)
            redis_conn.rpush("UiTestListQueue", str(case_log_id))

        if not self.is_run_flag:
            logger.info("无正在运行的，加入队列")
            self.is_run_flag = True
            case_log_id = add_uitest_log(ui_case_id)
            redis_conn.rpush("UiTestListQueue", str(case_log_id))

            self._run_ui_test()
